#pragma once

#include "defines.h"
#include "platform/vk/vk_device_context.h"
#include "platform/vk/vk_swapchain.h"
#include "platform/vk/vk_graphics_pipeline.h"
#include "platform/vk/vk_uniform_buffer.h"
#include "scene/grid.h"

namespace vkrender
{
    class GridRenderer
    {
        struct MVPMatrices
        {
            glm::mat4 model;
            glm::mat4 view;
            glm::mat4 proj;
        } ubo;

    public:
        std::shared_ptr<VulkanDeviceContext> context;
        std::shared_ptr<VulkanGraphicsPipeline> graphicsPipeline;
        VulkanSwapChain* swapchain;
        VkPipelineLayout pipelineLayout;
        VkDescriptorPool descriptorPool;
        VkDescriptorSetLayout descriptorSetLayout;
        std::vector<VkDescriptorSet> descriptorSets;
        std::vector<VulkanUniformBuffer> uniformBuffers;
    public:
        GridRenderer(
            const std::shared_ptr<VulkanDeviceContext>& context,
            const std::shared_ptr<VulkanSwapChain>& swapchain
        );
        ~GridRenderer();

        void bind(uint32_t imageIndex, VkCommandBuffer cmd, const glm::mat4& proj, const glm::mat4& view);
        void draw(uint32_t imageIndex, VkCommandBuffer cmd, const std::shared_ptr<Grid>& grid);

        void adjustForSwapchain(const std::shared_ptr<VulkanSwapChain>& swapchain);
    private:
        void createDescriptorPool();
        void createDescriptorSetLayout();
        void createPipelineLayout();
        void createPipeline();
        void createDescriptorSets();
        void createUniformBuffers();

        void updateDescriptorSets();
        void updateUniformBuffer(uint32_t imageIndex);
    };
}
